package com.egao.common.module.system.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.egao.common.component.timer.TimerUtils;
import com.egao.common.core.Constants;
import com.egao.common.core.annotation.ApiPageParam;
import com.egao.common.core.annotation.OperLog;
import com.egao.common.core.web.*;
import com.egao.common.core.utils.CoreUtil;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.entity.StudentInfo;
import com.egao.common.module.student.service.StudentInfoService;
import com.egao.common.module.student.service.StudentService;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.constants.EmailConstants;
import com.egao.common.module.system.entity.*;
import com.egao.common.module.system.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 用户管理
 *
 * @author system
 */
@Api(tags = "用户管理")
@RestController
@RequestMapping("${api}")
public class UserController extends BaseController {
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private DictService dictService;
    @Autowired
    private CollegeService collegeService;
    @Autowired
    private MajorService majorService;
    @Autowired
    private StudentService studentService;
    @Autowired
    private StudentInfoService studentInfoService;
    @Autowired
    private EmailService emailService;

    @PreAuthorize("hasAuthority('sys:user:list')")
    @OperLog(value = "用户管理", desc = "分页查询")
    @ApiOperation("分页查询用户")
    @ApiPageParam
    @GetMapping("/sys/user/page")
    public PageResult<User> page(HttpServletRequest request) {
        PageParam<User> pageParam = new PageParam<>(request);
        pageParam.setDefaultOrder(null, new String[]{"create_time"});
        return new PageResult<>(userService.listPage(pageParam), pageParam.getTotal());
    }

    @PreAuthorize("hasAuthority('sys:user:list')")
    @OperLog(value = "用户管理", desc = "查询全部")
    @ApiOperation("查询全部用户")
    @GetMapping("/sys/user")
    public JsonResult list(HttpServletRequest request) {
        PageParam<User> pageParam = new PageParam<>(request);
        List<User> records = userService.listAll(pageParam.getNoPageParam());
        return JsonResult.ok().setData(pageParam.sortRecords(records));
    }

    @PreAuthorize("hasAuthority('sys:user:list')")
    @OperLog(value = "用户管理", desc = "根据id查询")
    @ApiOperation("根据id查询用户")
    @GetMapping("/sys/user/{id}")
    public JsonResult get(@PathVariable("id") Integer id) {
        PageParam<User> pageParam = new PageParam<>();
        pageParam.put("userId", id);
        List<User> records = userService.listAll(pageParam.getNoPageParam());
        return JsonResult.ok().setData(pageParam.getOne(records));
    }

    @PreAuthorize("hasAuthority('sys:user:save')")
    @OperLog(value = "用户管理", desc = "添加", param = false, result = true)
    @ApiOperation("添加用户")
    @PostMapping("/sys/user")
    public JsonResult add(@RequestBody User user) {
        user.setState(0);
        user.setPassword(userService.encodePsw("mujin027."));
        if (userService.saveUser(user)) {
            return JsonResult.ok("添加成功");
        }
        return JsonResult.error("添加失败");
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "修改", param = false, result = true)
    @ApiOperation("修改用户")
    @PutMapping("/sys/user")
    public JsonResult update(@RequestBody User user) {
        user.setState(null);
        if (userService.updateUser(user)) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:user:remove')")
    @OperLog(value = "用户管理", desc = "删除", result = true)
    @ApiOperation("删除用户")
    @DeleteMapping("/sys/user/{id}")
    public JsonResult remove(@PathVariable("id") Integer id) {
        if (userService.removeById(id)) {
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "批量修改", param = false, result = true)
    @ApiOperation("批量修改用户")
    @PutMapping("/sys/user/batch")
    public JsonResult removeBatch(@RequestBody BatchParam<User> batchParam) {
        if (batchParam.update(userService, "user_id")) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:user:remove')")
    @OperLog(value = "用户管理", desc = "批量删除", result = true)
    @ApiOperation("批量删除用户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "id数组", required = true, dataType = "string")
    })
    @DeleteMapping("/sys/user/batch")
    public JsonResult deleteBatch(@RequestBody List<Integer> ids) {
        if (userService.removeByIds(ids)) {
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "修改状态", result = true)
    @ApiOperation("修改用户状态")
    @PutMapping("/sys/user/state/{id}")
    public JsonResult updateState(@PathVariable("id") Integer id, Integer state) {
        if (state == null || (state != 0 && state != 1)) {
            return JsonResult.error("状态值不正确");
        }
        User user = new User();
        user.setUserId(id);
        user.setState(state);
        user.setLoginCount(0);
        if (Constants.USER_STATE.equals(state)) {
            user.setLoginCount(0);
        }
        if (userService.updateById(user)) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "批量修改状态", result = true)
    @ApiOperation("批量修改用户状态")
    @PutMapping("/sys/user/state/batch")
    public JsonResult updateStateBatch(@RequestBody BatchParam<User> batchParam) {
        User user = new User();
        user.setState(batchParam.getData().getState());
        if (user.getState() == null || (user.getState() != 0 && user.getState() != 1)) {
            return JsonResult.error("状态值不正确");
        }
        if (batchParam.update(userService, "user_id")) {
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "重置密码", param = false, result = true)
    @ApiOperation("重置密码")
    @PutMapping("/sys/user/psw/{id}")
    public JsonResult resetPsw(@PathVariable("id") Integer id, String password) {
        User user = new User();
        user.setUserId(id);
        user.setPassword(userService.encodePsw(password));
        if (userService.updateById(user)) {
            return JsonResult.ok("重置成功");
        } else {
            return JsonResult.error("重置失败");
        }
    }

    @PreAuthorize("hasAuthority('sys:user:update')")
    @OperLog(value = "用户管理", desc = "批量重置密码", param = false, result = true)
    @ApiOperation("批量重置密码")
    @PutMapping("/sys/user/psw/batch")
    public JsonResult resetPswBatch(@RequestBody BatchParam<User> batchParam) {
        User user = new User();
        user.setPassword(userService.encodePsw(batchParam.getData().getPassword()));
        if (batchParam.update(userService, "user_id")) {
            return JsonResult.ok("重置成功");
        } else {
            return JsonResult.error("重置失败");
        }
    }

    /**
     * excel导入用户
     */
    @PreAuthorize("hasAuthority('sys:user:save')")
    @OperLog(value = "用户管理", desc = "excel导入", param = false, result = true)
    @ApiOperation("excel导入用户")
    @Transactional
    @PostMapping("/sys/user/import")
    public JsonResult importBatch(MultipartFile file) {
        StringBuilder sb = new StringBuilder();
        try {
            // 读取excel
            int startRow = 1;
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream(), 0);
            List<List<Object>> list = reader.read(startRow);
            // 进行非空和重复检查
            sb.append(CoreUtil.excelCheckBlank(list, startRow, 0, 1, 2, 3, 4, 7));
            sb.append(CoreUtil.excelCheckRepeat(list, startRow, 0, 5, 6));
            if (!sb.toString().isEmpty()) {
                return JsonResult.error(sb.toString());
            }
            // 进行数据库层面检查
            List<User> users = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                List<Object> objects = list.get(i);
                String username = String.valueOf(objects.get(0));  // 账号
                String password = String.valueOf(objects.get(1));  // 密码
                String sexName = String.valueOf(objects.get(3));  // 性别
                String roleName = String.valueOf(objects.get(4));  // 角色名
                String phone = String.valueOf(objects.get(5));  // 手机号
                String email = String.valueOf(objects.get(6));  // 邮箱
                String orgName = String.valueOf(objects.get(7));  // 组织机构
                if (userService.count(new QueryWrapper<User>().eq("username", username)) > 0) {
                    sb.append("第");
                    sb.append(i + startRow + 1);
                    sb.append("行第1");
                    sb.append("列账号已存在;\r\n");
                }
                if (StrUtil.isNotBlank(phone) && userService.count(new QueryWrapper<User>().eq("phone", phone)) > 0) {
                    sb.append("第");
                    sb.append(i + startRow + 1);
                    sb.append("行第6");
                    sb.append("列手机号已存在;\r\n");
                }
                if (StrUtil.isNotBlank(email) && userService.count(new QueryWrapper<User>().eq("email", email)) > 0) {
                    sb.append("第");
                    sb.append(i + startRow + 1);
                    sb.append("行第7");
                    sb.append("列邮箱已存在;\r\n");
                }
                User user = new User();
                user.setUsername(username);
                user.setPassword(userService.encodePsw(password));
                user.setState(0);
                user.setEmail(email);

                Role role = roleService.getOne(new QueryWrapper<Role>().eq("role_name", roleName), false);
                if (role == null) {
                    sb.append("第");
                    sb.append(i + startRow + 1);
                    sb.append("行第5");
                    sb.append("列角色不存在;\r\n");
                } else {
                    user.setRoleIds(Collections.singletonList(role.getRoleId()));
                }
                users.add(user);
            }
            if (!sb.toString().isEmpty()) {
                return JsonResult.error(sb.toString());
            }
            // 开始添加用户
            int okNum = 0, errorNum = 0;
            for (User user : users) {
                if (userService.saveUser(user)) {
                    okNum++;
                } else {
                    errorNum++;
                }
            }
            return JsonResult.ok("导入完成，成功" + okNum + "条，失败" + errorNum + "条");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return JsonResult.error("导入失败");
    }

    @PreAuthorize("hasAuthority('sys:user:save')")
    @OperLog(value = "用户管理", desc = "导入学生用户")
    @ApiOperation("导入学生用户")
    @Transactional
    @PostMapping("/sys/user/import-student")
    public JsonResult importStudent(MultipartFile file) {
        StringBuilder sb = new StringBuilder();
        String[] email = {"346907006@qq.com"};
        try {
            // 读取excel
            int startRow = 1;
            ExcelReader reader = ExcelUtil.getReader(file.getInputStream(), 0);
            List<List<Object>> list = reader.read(startRow);

            TimeInterval timer = DateUtil.timer();

            // 进行数据库层面检查
            int count = 0;
            List<User> users = new ArrayList<>();

            List<Dict> dictXl = dictService.cacheList(DictConstants.TYPE_XL);
            List<Dict> dictPyfs = dictService.cacheList(DictConstants.TYPE_PYFS);
            List<Dict> dictXb = dictService.cacheList(DictConstants.TYPE_XB);
            List<Dict> dictXw = dictService.cacheList(DictConstants.TYPE_XW);
            List<Dict> dictXwlb = dictService.cacheList(DictConstants.TYPE_XWLB);
            List<Dict> dictXxfs = dictService.cacheList(DictConstants.TYPE_XXFS);
            List<Dict> dictXjzt = dictService.cacheList(DictConstants.TYPE_XJZT);
            List<Dict> dictZzmm = dictService.cacheList(DictConstants.TYPE_ZZMM);
            List<Dict> dictMz = dictService.cacheList(DictConstants.TYPE_MZ);
            List<Dict> dictZxjh = dictService.cacheList(DictConstants.TYPE_ZXJH);

            List<College> collegeList = collegeService.list();
            List<Major> majorList = majorService.list();

            int id = 200000;
            for (int i = 0; i < list.size(); i++) {
//                if (i == 10) {
//                    long time = timer.intervalMinute();
//                    emailService.sendTextEmail("导入10", "导入10-" + time, email);
//                }
//
//                if (i == 100) {
//                    long time = timer.intervalMinute();
//                    emailService.sendTextEmail("导入100", "导入100-" + time, email);
//                }
//
//                if (i == 1000) {
//                    long time = timer.intervalMinute();
//                    emailService.sendTextEmail("导入1000", "导入1000-" + time, email);
//                }
//
//                if (i == 5000) {
//                    long time = timer.intervalMinute();
//                    emailService.sendTextEmail("导入5000", "导入5000-" + time, email);
//                }

                List<Object> objects = list.get(i);
                String username = String.valueOf(objects.get(0));
                String name = String.valueOf(objects.get(1));
                String collegeName = String.valueOf(objects.get(2));
                String majorName = String.valueOf(objects.get(3));
                String pyfs = String.valueOf(objects.get(4));
                String bjhm = String.valueOf(objects.get(5));
                String xb = String.valueOf(objects.get(6));
                String xl = String.valueOf(objects.get(7));
                String xz = String.valueOf(objects.get(8));
                String xw = String.valueOf(objects.get(9));
                String xwlb = String.valueOf(objects.get(10));
                String csrq = String.valueOf(objects.get(11));
                String rxsj = String.valueOf(objects.get(12));
                String bysj = String.valueOf(objects.get(13));
                String cxsy = String.valueOf(objects.get(14));
                String xxfs = String.valueOf(objects.get(15));
                String syszd = String.valueOf(objects.get(16));
                String sysf = String.valueOf(objects.get(17));
                String sfzhm = String.valueOf(objects.get(18));
                String ksh = String.valueOf(objects.get(19));
                String zxjh = String.valueOf(objects.get(20));
                String xjzt = String.valueOf(objects.get(21));
                String zzmm = String.valueOf(objects.get(22));
                String mz = String.valueOf(objects.get(23));
                String bz = String.valueOf(objects.get(24));

                String dxwpdw = String.valueOf(objects.get(25));
                String mobile = String.valueOf(objects.get(26));
                String emails = String.valueOf(objects.get(27));

                String password = IdUtil.simpleUUID();

                String xlValue = getValue(dictXl, xl);
                if ("31".equals(xlValue) || "25".equals(xlValue)) {
                    xl = "1";
                } else {
                    xl = "2";
                }

                String x = xl;

                College college = collegeList.stream().filter(d -> d.getName().equals(collegeName.trim()) && x.equals(d.getXl().toString())).findFirst().orElse(null);
                String collegeCode = "";
                if (college != null) {
                    collegeCode = college.getCode();
                } else {
                    collegeCode = "";
                }
                String cc = collegeCode;

                Major major = majorList.stream().filter(d -> d.getName().equals(majorName.trim()) && d.getCollegeCode().equals(cc)).findFirst().orElse(null);
                String majorCode = "";
                if (major != null) {
                    majorCode = major.getCode();
                } else {
                    majorCode = "";
                }

                User user = new User();
                user.setUserId(id);
                user.setUsername(username);
                user.setName(name);
                user.setCollegeCode(collegeCode);
                user.setPassword(userService.encodePsw(password));
                user.setState(0);
                users.add(user);

                User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
                if (one != null) {
                    user.setUserId(one.getUserId());
                    userService.updateById(user);
                } else {
                    user = userService.saveUserStudent(user);
                }

                Student student = new Student();
                student.setId(id);
                student.setYearId(2025);
                student.setUserId(user.getUserId());
                student.setXh(username);
                student.setXm(name);
                student.setCollegeCode(collegeCode);
                student.setMajorCode(majorCode);
                student.setPyfs(getValue(dictPyfs, pyfs));
                student.setBjhm(bjhm);
                student.setXb(getValue(dictXb, xb));
                student.setXl(xlValue);
                student.setDegree(xl);
                student.setXz(Integer.parseInt(xz));
                student.setXw(getValue(dictXw, xw));
                student.setXwlb(getValue(dictXwlb, xwlb));
                student.setCsrq(DateUtil.parse(csrq));
                student.setRxsj(DateUtil.parse(rxsj));
                student.setBysj(DateUtil.parse(bysj));
                student.setCxsydm("");
                student.setXxfs(getValue(dictXxfs, xxfs));
                student.setSyszd("");
                student.setSysf(sysf);
                student.setSfzhm(sfzhm);
                student.setKsh(ksh);
                student.setXjzt(getValue(dictXjzt, xjzt));
                student.setZzmm(getValue(dictZzmm, zzmm));
                student.setMz(getValue(dictMz, mz));
                student.setMobile(mobile);
                student.setEmail(emails);

                Student oldStudent = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getXh, username));
                if (oldStudent != null) {
                    student.setId(oldStudent.getId());
                    studentService.updateById(student);

                    StudentInfo oldStudentInfo = studentInfoService.getOne(new LambdaQueryWrapper<StudentInfo>().eq(StudentInfo::getXh, username));
                    StudentInfo studentInfo = new StudentInfo();
                    studentInfo.setStudentId(student.getId());
                    studentInfo.setUserId(student.getUserId());
                    studentInfo.setXh(student.getXh());
                    studentInfo.setDxhwpdw(dxwpdw);
                    studentInfo.setZxjh(getValue(dictZxjh, zxjh));
                    if (oldStudentInfo != null) {
                        studentInfo.setId(oldStudentInfo.getId());
                    }
                    studentInfoService.saveOrUpdate(studentInfo);

                } else {
                    studentService.save(student);

                    StudentInfo studentInfo = new StudentInfo();
                    studentInfo.setId(id);
                    studentInfo.setStudentId(student.getId());
                    studentInfo.setUserId(student.getUserId());
                    studentInfo.setXh(student.getXh());
                    studentInfo.setDxhwpdw(dxwpdw);
                    studentInfo.setZxjh(getValue(dictZxjh, zxjh));
                    studentInfoService.save(studentInfo);
                }
                count++;
                id++;
            }

//            emailService.sendTextEmail("导入完成通知", "导入学生共" + list.size() + "条完成：" + count + "条", email);
            return JsonResult.ok("导入完成");
        } catch (IOException e) {
//            emailService.sendTextEmail("导入失败通知", e.getMessage(), email);
            e.printStackTrace();
        }
        return JsonResult.error("导入失败");
    }

    private String getValue(List<Dict> dictList, String label) {
        for (Dict dict : dictList) {
            if (dict.getLabel().equals(label)) {
                return dict.getValue();
            }
        }
        return "";
    }

}
